HDU 5636 Shortest Path(floyd)

题意:

$N,M\le 10^5,N个点M条边的形成一条链的无向图$
$即只有(i,i+1,1)这样的边,i\in[1,N)$
$现在添加3条长度为1的边,Q次询问dis(a,b)$

分析:

$把这6个点floyd一下,然后暴力枚举经过这6个点中的2个点,或者不经过$
$时间复杂度为O(6^2\cdot m)$
$当然建图跑spfa也可以,求dis[6][N],枚举经过这6个点中的1个点,或者不经过$
$时间复杂度为O(6m)$

代码:

//
//  Created by TaoSama on 2016-04-06
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, m, a[4], b[4];
int g[7][7];

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    int t; scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        vector<int> v;
        for(int i = 1; i <= 3; ++i) {
            scanf("%d%d", a + i, b + i);
            v.push_back(a[i]);
            v.push_back(b[i]);
        }
        sort(v.begin(), v.end());
        v.resize(unique(v.begin(), v.end()) - v.begin());

        int sz = v.size();
        for(int i = 1; i <= sz; ++i)
            for(int j = 1; j <= sz; ++j)
                g[i][j] = abs(v[i - 1] - v[j - 1]);
        for(int i = 1; i <= 3; ++i) {
            int x = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
            int y = lower_bound(v.begin(), v.end(), b[i]) - v.begin() + 1;
            g[x][y] = min(g[x][y], 1);
            g[y][x] = min(g[y][x], 1);
        }
        for(int k = 1; k <= sz; ++k)
            for(int i = 1; i <= sz; ++i)
                for(int j = 1; j <= sz; ++j)
                    g[i][j] = min(g[i][j], g[i][k] + g[k][j]);

        int ans = 0;
        for(int i = 1; i <= m; ++i) {
            int x, y; scanf("%d%d", &x, &y);

            int cur = abs(x - y);
            for(int j = 1; j <= sz; ++j)
                for(int k = 1; k <= sz; ++k)
                    cur = min(cur, abs(x - v[j - 1]) + g[j][k] + abs(y - v[k - 1]));

            ans += 1LL * i * cur % MOD;
            if(ans >= MOD) ans -= MOD;
        }
        printf("%d\n", ans);
    }
    return 0;
}